package pers.lolicer.redtidelibrary.components

import AppColor
import android.annotation.SuppressLint
import android.content.Context
import android.util.Log
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.ModalBottomSheetDefaults
import androidx.compose.material3.ModalBottomSheetProperties
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.focus.onFocusEvent
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.ConstraintSet
import androidx.core.net.toUri
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import pers.lolicer.redtidelibrary.R
import pers.lolicer.redtidelibrary.repository.MyDatabase
import pers.lolicer.redtidelibrary.repository.entity.BookEntity
import pers.lolicer.redtidelibrary.utils.FileUtils
import pers.lolicer.redtidelibrary.utils.sundayMatch
import pers.lolicer.redtidelibrary.utils.toDateStr

@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun BookList(
    allBooks: List<BookEntity>,
    sortMethod: Int,
    foldersSet: Set<String>,
    folderFilter: String,
    searchFilter:String,
    isDataSync: MutableState<Boolean>
) {
    val context = LocalContext.current

    val showBottomSheet = remember { mutableStateOf(false) }
    val entityToBeChangedInBottomSheet = remember { mutableStateOf(BookEntity("", "", "", 0, 0)) }

    var isWaiting by remember { mutableStateOf(true) }

    if(showBottomSheet.value){
        BookChangingSheet(context, foldersSet, showBottomSheet, entityToBeChangedInBottomSheet.value, isDataSync)
    }

    // val bookList = remember{ mutableStateOf(sortAndFilter(context, allBooks.value, sortMethod, folderFilter, searchFilter)) }
     val bookList = sortAndFilter(allBooks, sortMethod, folderFilter, searchFilter)


    LaunchedEffect(Unit){
        delay(100)
        isWaiting = false
    }
    if(!isWaiting){
        Column(modifier = Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState())
        ){
            bookList.forEach { entity ->
                ListItem(context, entity, isDataSync, showBottomSheet, entityToBeChangedInBottomSheet)
            }
        }
    }
}

@SuppressLint("CoroutineCreationDuringComposition", "UnusedBoxWithConstraintsScope")
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ListItem(
    context: Context,
    entity: BookEntity,
    isDataSync: MutableState<Boolean>,
    showBottomSheet: MutableState<Boolean>,
    entityToBeModifiedInBottomSheet: MutableState<BookEntity>
){
    val bookNameNow = FileUtils().getDisplayNameFromUri(context, entity.uriString.toUri())
    val scope = rememberCoroutineScope()

    val constraints = bookCardConstraints()
    Card(
        shape = RoundedCornerShape(8.dp),
        colors = AppColor.BookListCard(context),
        modifier = Modifier
            .fillMaxWidth()
            .height(128.dp)
            .padding(4.dp)
            .shadow(
                elevation = 4.dp,
                shape = RoundedCornerShape(8.dp)
            )
            .combinedClickable(
                onClick = {
                    if(bookNameNow != "") {
                        scope.launch {
                            delay(100)
                            FileUtils().openFile(context, entity.uriString.toUri())
                            isDataSync.value = false
                        }
                    }
                },
                onLongClick = {
                    showBottomSheet.value = true
                    entityToBeModifiedInBottomSheet.value = entity
                },
                indication = LocalIndication.current,
                interactionSource = remember {MutableInteractionSource()})
    ) {
        BoxWithConstraints{
            val maxWidth = maxWidth
            val maxHeight = maxHeight
            ConstraintLayout(constraints){
                Image(
                    modifier = Modifier
                        .layoutId("cover")
                        .width(maxWidth * 0.18f),
                    bitmap = FileUtils().getCoverFromUri(context, entity.uriString.toUri()),
                    contentDescription = ""
                )
                Text(
                    modifier = Modifier
                        .layoutId("bookName")
                        .width(maxWidth * 0.7f),
                    text = if(bookNameNow == "") "【文件状态异常】"+entity.book_name else bookNameNow ,
                    maxLines = 3,
                    minLines = 3
                )
                Text(
                    text = "打开时间：" + entity.time_last_open.toDateStr("MM-dd HH:mm:ss"),
                    fontSize = 8.sp,
                    modifier = Modifier
                        .padding(horizontal = 8.dp)
                        .height(20.dp)
                        .layoutId("timeLastOpen")
                )
            }
        }
    }
}

@SuppressLint("UnusedBoxWithConstraintsScope")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BookChangingSheet(
    context: Context,
    foldersSet: Set<String>,
    showBottomSheet: MutableState<Boolean>,
    entity: BookEntity,
    isDataSync: MutableState<Boolean>
){ModalBottomSheet(
        onDismissRequest = {
            showBottomSheet.value = false
        }
    ){
        var textFieldValueState by remember { mutableStateOf(
            TextFieldValue(text = entity.folder, selection = TextRange(entity.folder.length))
        ) }

        val foldersListWithSearch: MutableList<String> = mutableListOf()
        foldersSet.forEach{ folder ->
            if(folder.sundayMatch(textFieldValueState.text))
                foldersListWithSearch.add(folder)
        }

        val constraints = bookChangingSheetConstraints()
        BoxWithConstraints{
            ConstraintLayout(constraints) {
                OutlinedTextField(
                    modifier = Modifier
                        .width(216.dp)
                        .layoutId("textField"),
                    label = { Text("修改文件夹")},
                    placeholder = { Text(text = "文件夹名不能为空") },
                    value = textFieldValueState,
                    onValueChange = {newTextFieldValue ->
                        val text = newTextFieldValue.text.replace("\n", "")
                        textFieldValueState = TextFieldValue(text = text, selection = TextRange(text.length))
                    },
                    singleLine = true
                )

                Text(
                    modifier = Modifier.layoutId("text"),
                    text = "您可能在找：",
                    fontSize = 8.sp
                )

                Row(
                    modifier = Modifier
                        .height(64.dp)
                        .padding(end = 16.dp)
                        .horizontalScroll(rememberScrollState())
                        .layoutId("folderList")
                ) {
                    foldersListWithSearch.forEach{ folder ->
                        Button(
                            shape = RoundedCornerShape(8.dp),
                            colors = AppColor.MaybeLookingForButton(context),
                            modifier = Modifier
                                .padding(4.dp),
                            onClick = {
                                textFieldValueState = TextFieldValue(
                                    text = folder,
                                    selection = TextRange(folder.length)
                                )
                            }
                        ) {
                            Text(text = folder, maxLines = 1, fontSize = 12.sp)
                        }
                    }
                }

                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .layoutId("buttonsRow"),
                    horizontalArrangement = Arrangement.SpaceAround
                ){
                    val bookDao = MyDatabase.getDB(context).getBookDao()

                    Button(
                        colors = AppColor.DeleteButton(context),
                        onClick = {
                            showBottomSheet.value = false
                            isDataSync.value = false
                            CoroutineScope(Dispatchers.IO).launch {
                                bookDao.deleteBookByUri(entity.uriString)
                            }
                        }
                    ) {
                        Text("删除")
                    }
                    // 确认更改
                    Button(
                        colors = AppColor.ConfirmButton(context),
                        onClick = {
                            if(textFieldValueState.text != ""){
                                showBottomSheet.value = false
                                isDataSync.value = false
                                CoroutineScope(Dispatchers.IO).launch {
                                    bookDao.updateFolderByUri(textFieldValueState.text, entity.uriString)
                                }
                            }
                        }) {
                        Text("确认")
                    }
                }

                Spacer(
                    modifier = Modifier
                        .height(
                            WindowInsets.navigationBars
                                .asPaddingValues()
                                .calculateBottomPadding()
                        )
                        .layoutId("spacer")
                )
            }
        }
    }
}

/**
 * 对书籍列表进行排序和筛选
 *
 * @param folderFilter 筛选条件，后续进行完善。
 * */
fun sortAndFilter(
    originalBookList: List<BookEntity>,
    sortMethod: Int,
    folderFilter: String,
    searchFilter: String
): List<BookEntity>{
    var res = originalBookList

    if(folderFilter != "")
        res = res.filter { it.folder == folderFilter }

    if(searchFilter != "")
            res = res.filter{ it.book_name.sundayMatch(searchFilter) }

    res = when(sortMethod){
        R.integer.sortMethod_time_import -> {
            Log.d("Set Sort Method", "time_import")
            res.sortedBy { it.time_import }.reversed()
        }
        R.integer.sortMethod_time_last_open -> {
            Log.d("Set Sort Method", "time_last_open")
            res.sortedBy { it.time_last_open }.reversed()
        }
        else -> {
            throw Exception("Error: 代码逻辑出错：未知排序方式！")
        }
    }
    return res
}

fun bookCardConstraints(): ConstraintSet{
    val margin = 8.dp
    return ConstraintSet{
        val cover = createRefFor("cover")
        val coverBackground = createRefFor("coverBackground")
        val bookName = createRefFor("bookName")
        val timeLastOpen = createRefFor("timeLastOpen")

        constrain(cover){
            start.linkTo(parent.start, margin = margin)
            top.linkTo(parent.top, margin = margin)
        }
        constrain(coverBackground){
            start.linkTo(cover.start)
            end.linkTo(cover.end)
            top.linkTo(cover.top)
            bottom.linkTo(cover.bottom)
        }
        constrain(bookName){
            start.linkTo(cover.end, margin = margin)
            end.linkTo(parent.end)
            top.linkTo(parent.top)
            bottom.linkTo(cover.bottom)
        }
        constrain(timeLastOpen){
            start.linkTo(parent.start)
            top.linkTo(cover.bottom)
            bottom.linkTo(parent.bottom)
        }
    }
}

fun bookChangingSheetConstraints(): ConstraintSet{
    return ConstraintSet{
        val textField = createRefFor("textField")
        val text = createRefFor("text")
        val folderList = createRefFor("folderList")
        val buttonsRow = createRefFor("buttonsRow")
        val spacer = createRefFor("spacer")

        val margin = 8.dp

        constrain(textField){
            start.linkTo(parent.start, margin = margin)
            top.linkTo(parent.top)
        }
        constrain(text){
            start.linkTo(parent.start, margin = margin)
            top.linkTo(textField.bottom)
        }
        constrain(folderList){
            start.linkTo(text.end)
            top.linkTo(text.top)
        }
        constrain(buttonsRow){
            start.linkTo(parent.start)
            end.linkTo(parent.end)
            top.linkTo(folderList.bottom)
            bottom.linkTo(spacer.top)
        }
        constrain(spacer){
            start.linkTo(parent.start)
            end.linkTo(parent.end)
            bottom.linkTo(parent.bottom)
        }
    }
}